package juc.scenarios.order;

import java.util.concurrent.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 电商订单异步处理系统演示
 * 使用CompletableFuture和线程池处理订单的多个异步操作
 */
public class OrderAsyncProcessingDemo {
    
    // 自定义线程池
    private static final ExecutorService ORDER_EXECUTOR = new ThreadPoolExecutor(
            4, 8, 60L, TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(1000),
            new ThreadFactory() {
                private final AtomicInteger threadNumber = new AtomicInteger(1);
                
                @Override
                public Thread newThread(Runnable r) {
                    Thread t = new Thread(r, "order-processor-" + threadNumber.getAndIncrement());
                    t.setDaemon(false);
                    return t;
                }
            },
            new ThreadPoolExecutor.CallerRunsPolicy()
    );
    
    public static void main(String[] args) {
        System.out.println("=== 电商订单异步处理系统演示 ===\n");
        
        // 创建订单服务
        OrderService orderService = new OrderService();
        
        // 模拟用户下单
        Order order = new Order("ORD-" + System.currentTimeMillis(), 1001L, 2999.99);
        System.out.println("用户下单：" + order);
        
        long startTime = System.currentTimeMillis();
        
        try {
            // 处理订单
            OrderResult result = orderService.processOrder(order);
            
            long endTime = System.currentTimeMillis();
            System.out.println("\n=== 订单处理完成 ===");
            System.out.println("总耗时：" + (endTime - startTime) + "ms");
            System.out.println("处理结果：" + result);
            
        } catch (Exception e) {
            System.err.println("订单处理失败：" + e.getMessage());
            e.printStackTrace();
        } finally {
            // 关闭线程池
            ORDER_EXECUTOR.shutdown();
            try {
                if (!ORDER_EXECUTOR.awaitTermination(60, TimeUnit.SECONDS)) {
                    ORDER_EXECUTOR.shutdownNow();
                }
            } catch (InterruptedException e) {
                ORDER_EXECUTOR.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }
    
    /**
     * 订单实体类
     */
    static class Order {
        private final String orderId;
        private final Long userId;
        private final Double amount;
        
        public Order(String orderId, Long userId, Double amount) {
            this.orderId = orderId;
            this.userId = userId;
            this.amount = amount;
        }
        
        // Getters
        public String getOrderId() { return orderId; }
        public Long getUserId() { return userId; }
        public Double getAmount() { return amount; }
        
        @Override
        public String toString() {
            return "Order{orderId='" + orderId + "', userId=" + userId + ", amount=" + amount + "}";
        }
    }
    
    /**
     * 订单处理结果
     */
    static class OrderResult {
        private final String orderId;
        private final boolean success;
        private final String message;
        private final Map<String, Object> details;
        
        public OrderResult(String orderId, boolean success, String message, Map<String, Object> details) {
            this.orderId = orderId;
            this.success = success;
            this.message = message;
            this.details = details;
        }
        
        @Override
        public String toString() {
            return "OrderResult{orderId='" + orderId + "', success=" + success + 
                   ", message='" + message + "', details=" + details + "}";
        }
    }
    
    /**
     * 订单服务
     */
    static class OrderService {
        
        /**
         * 处理订单 - 使用CompletableFuture并行处理
         */
        public OrderResult processOrder(Order order) throws Exception {
            System.out.println("开始处理订单：" + order.getOrderId());
            
            try {
                // 1. 库存扣减（可与其他操作并行）
                CompletableFuture<Boolean> inventoryFuture = CompletableFuture.supplyAsync(() -> {
                    return reduceInventory(order);
                }, ORDER_EXECUTOR);
                
                // 2. 优惠券核销（可与其他操作并行）
                CompletableFuture<String> couponFuture = CompletableFuture.supplyAsync(() -> {
                    return useCoupon(order);
                }, ORDER_EXECUTOR);
                
                // 3. 积分计算（可与其他操作并行）
                CompletableFuture<Integer> pointsFuture = CompletableFuture.supplyAsync(() -> {
                    return calculatePoints(order);
                }, ORDER_EXECUTOR);
                
                // 4. 消息通知（依赖订单基础信息）
                CompletableFuture<Boolean> notificationFuture = CompletableFuture.supplyAsync(() -> {
                    return sendNotification(order);
                }, ORDER_EXECUTOR);
                
                // 5. 日志记录（依赖前面操作的结果）
                CompletableFuture<Boolean> logFuture = CompletableFuture.allOf(
                    inventoryFuture, couponFuture, pointsFuture, notificationFuture
                ).thenApplyAsync(v -> {
                    try {
                        Boolean inventoryResult = inventoryFuture.get();
                        String couponResult = couponFuture.get();
                        Integer pointsResult = pointsFuture.get();
                        Boolean notificationResult = notificationFuture.get();
                        
                        return recordLog(order, inventoryResult, couponResult, 
                                       pointsResult, notificationResult);
                    } catch (Exception e) {
                        System.err.println("日志记录失败：" + e.getMessage());
                        return false;
                    }
                }, ORDER_EXECUTOR);
                
                // 等待所有操作完成（设置超时）
                CompletableFuture<Void> allTasks = CompletableFuture.allOf(
                    inventoryFuture, couponFuture, pointsFuture, notificationFuture, logFuture
                );
                
                // 等待最多10秒
                allTasks.get(10, TimeUnit.SECONDS);
                
                // 收集结果
                Map<String, Object> details = new HashMap<>();
                details.put("inventoryReduced", inventoryFuture.get());
                details.put("couponUsed", couponFuture.get());
                details.put("pointsEarned", pointsFuture.get());
                details.put("notificationSent", notificationFuture.get());
                details.put("logRecorded", logFuture.get());
                
                boolean allSuccess = inventoryFuture.get() && notificationFuture.get() && 
                                 logFuture.get() && pointsFuture.get() > 0;
                
                String message = allSuccess ? "订单处理成功" : "订单处理部分失败";
                
                return new OrderResult(order.getOrderId(), allSuccess, message, details);
                
            } catch (TimeoutException e) {
                throw new Exception("订单处理超时", e);
            } catch (Exception e) {
                throw new Exception("订单处理失败：" + e.getMessage(), e);
            }
        }
        
        /**
         * 库存扣减
         */
        private boolean reduceInventory(Order order) {
            try {
                System.out.println("开始库存扣减...");
                Thread.sleep(500); // 模拟数据库操作
                
                // 模拟库存检查
                if (Math.random() > 0.1) { // 90%成功率
                    System.out.println("库存扣减成功");
                    return true;
                } else {
                    System.err.println("库存不足");
                    return false;
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return false;
            }
        }
        
        /**
         * 优惠券核销
         */
        private String useCoupon(Order order) {
            try {
                System.out.println("开始优惠券核销...");
                Thread.sleep(300); // 模拟API调用
                
                // 模拟优惠券使用
                if (Math.random() > 0.2) { // 80%成功率
                    String couponCode = "COUPON-" + (int)(Math.random() * 10000);
                    System.out.println("优惠券核销成功：" + couponCode);
                    return couponCode;
                } else {
                    System.err.println("优惠券已过期或无效");
                    return null;
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return null;
            }
        }
        
        /**
         * 积分计算
         */
        private int calculatePoints(Order order) {
            try {
                System.out.println("开始积分计算...");
                Thread.sleep(200); // 模拟计算
                
                // 模拟积分计算：订单金额的10%
                int points = (int)(order.getAmount() * 0.1);
                System.out.println("积分计算完成：" + points + "分");
                return points;
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return 0;
            }
        }
        
        /**
         * 消息通知
         */
        private boolean sendNotification(Order order) {
            try {
                System.out.println("开始消息通知...");
                Thread.sleep(400); // 模拟消息发送
                
                // 模拟消息发送
                if (Math.random() > 0.15) { // 85%成功率
                    System.out.println("消息通知成功");
                    return true;
                } else {
                    System.err.println("消息通知失败");
                    return false;
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return false;
            }
        }
        
        /**
         * 日志记录
         */
        private boolean recordLog(Order order, Boolean inventoryResult, String couponResult, 
                                Integer pointsResult, Boolean notificationResult) {
            try {
                System.out.println("开始日志记录...");
                Thread.sleep(100); // 模拟日志写入
                
                String logContent = String.format("订单[%s]处理完成：库存=%s, 优惠券=%s, 积分=%d, 通知=%s",
                    order.getOrderId(), inventoryResult, couponResult, pointsResult, notificationResult);
                
                System.out.println("日志记录完成：" + logContent);
                return true;
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return false;
            }
        }
    }
}